package handlersvc

import (
	"encoding/json"
	"fmt"
	"server/application/services/aiservice"
	"server/pkg/ginp"
	"server/pkg/utils"
	"strconv"
	"strings"
)

type PlaceInfo struct {
	Name        string  `json:"name"`        // 地点名称
	Longitude   float64 `json:"longitude"`   // 经度
	Latitude    float64 `json:"latitude"`    // 纬度
	Description string  `json:"description"` // 描述
	Transport   string  `json:"transport"`   // 交通方式
	TheDay      int     `json:"the_day"`     // 天数
}

type HandlerCore struct {
	sse            *aiservice.SSEStreamManager
	receiveContent string
	PlaceList      [][]PlaceInfo
	lastReturnPos  int
	isFinished     bool
}

// NewHandlerCore 创建一个新的 HandlerCore 实例
func NewHandlerCore() *HandlerCore {
	return &HandlerCore{
		sse: aiservice.NewSSEStreamManager(),
	}
}

// 处理消息的回调函数
func (s *HandlerCore) Handler(data *aiservice.StreamRespData, ctx *ginp.ContextPro, statusCode string) {
	if statusCode == aiservice.StrStreamEnd { //结束接受
		s.ParseToPlaceList() // 解析完整数据
		fmt.Println(utils.DataToJsonStr(s.PlaceList))
		s.WriteRespond(ctx, s.PlaceList)
		s.isFinished = true
		return
	} else if statusCode == aiservice.StrRequestError { //请求通义千问服务器错误
		s.isFinished = true
		s.WriteRespond(ctx, statusCode)
		return
	}

	place := s.handlerStreamText(data.Output.Text)
	if place.Name != "" {
		fmt.Println(utils.DataToJsonStr(place))
		s.WriteRespond(ctx, place)
	}
}
func (s *HandlerCore) WriteRespond(ctx *ginp.ContextPro, data any) {
	s.sse.SendTongyi(ctx.Context, data)
}

// handlerStreamText 处理流式文本数据，从中提取最新的地点信息
func (s *HandlerCore) handlerStreamText(streamText string) PlaceInfo {
	// 清理输入文本
	streamText = strings.ReplaceAll(streamText, " ", "")   // 去除空格
	streamText = strings.ReplaceAll(streamText, "\n", "")  // 去除换行符
	streamText = strings.ReplaceAll(streamText, "\r", "")  // 去除回车符
	streamText = strings.ReplaceAll(streamText, "```", "") // 去除反引号

	s.receiveContent += streamText

	// 使用计数器追踪嵌套的方括号
	bracketCount := 0
	lastStart := -1

	content := s.receiveContent
	var newPlace PlaceInfo
	var newPlacePos int = -1

	// 解析逻辑
	bracketCount = 0
	for i, char := range content {
		if char == '[' {
			bracketCount++
			if bracketCount == 3 { // 进入第三维度数组
				lastStart = i
			}
		} else if char == ']' {
			bracketCount--
			if bracketCount == 2 && lastStart != -1 && lastStart > s.lastReturnPos { // 完成一个地点信息的接收
				// 提取单个地点的数组内容
				placeArray := content[lastStart : i+1]
				// 解析成标准的数组格式
				var placeData []interface{}
				err := json.Unmarshal([]byte(placeArray), &placeData)
				if err == nil && len(placeData) >= 6 {
					// 直接从数组中获取对应的值
					name := placeData[0].(string)

					// 安全地处理经度
					var longitude float64
					switch v := placeData[1].(type) {
					case float64:
						longitude = v
					case string:
						longitude, _ = strconv.ParseFloat(v, 64)
					}

					// 安全地处理纬度
					var latitude float64
					switch v := placeData[2].(type) {
					case float64:
						latitude = v
					case string:
						latitude, _ = strconv.ParseFloat(v, 64)
					}

					description := placeData[3].(string)
					transport := placeData[4].(string)

					// 安全地处理天数
					var theDay int
					switch v := placeData[5].(type) {
					case float64:
						theDay = int(v)
					case string:
						theDay64, _ := strconv.ParseFloat(v, 64)
						theDay = int(theDay64)
					}

					newPlace = PlaceInfo{
						Name:        name,
						Longitude:   longitude,
						Latitude:    latitude,
						Description: description,
						Transport:   transport,
						TheDay:      theDay,
					}
					newPlacePos = i
					break
				}
			}
		}
	}

	if newPlacePos > s.lastReturnPos {
		s.lastReturnPos = newPlacePos
		return newPlace
	}

	return PlaceInfo{} // 如果没有新的地点信息，返回空结构体
}

// 解析完整的接收内容到PlaceList// 解析完整的接收内容到PlaceList
func (s *HandlerCore) ParseToPlaceList() {
	if s.receiveContent == "" {
		return
	}

	// 解析JSON到三维数组
	var rawData [][][]interface{}
	err := json.Unmarshal([]byte(s.receiveContent), &rawData)
	if err != nil {
		fmt.Println("解析JSON失败:", err)
		return
	}

	// 转换为PlaceList
	placeList := make([][]PlaceInfo, len(rawData))
	for day, dayPlaces := range rawData {
		placeList[day] = make([]PlaceInfo, len(dayPlaces))
		for i, place := range dayPlaces {
			if len(place) >= 5 {
				// 安全地转换数值类型
				var longitude, latitude float64
				switch v := place[1].(type) {
				case float64:
					longitude = v
				case string:
					longitude, _ = strconv.ParseFloat(v, 64)
				}
				switch v := place[2].(type) {
				case float64:
					latitude = v
				case string:
					latitude, _ = strconv.ParseFloat(v, 64)
				}

				placeList[day][i] = PlaceInfo{
					Name:        place[0].(string),
					Longitude:   longitude,
					Latitude:    latitude,
					Description: place[3].(string),
					Transport:   place[4].(string),
					TheDay:      day + 1, // 天数从1开始
				}
			}
		}
	}

	s.PlaceList = placeList
}
